﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Citi.Import.Util;

namespace Citi.GocAttributes.Domain
{
    public abstract class LevelParentImport<T> where T : Utils.GeneralAction
    {
        #region Import Validation

        protected abstract string IdColumnName { get; }
        protected abstract string DescriptionColumnName { get; }
        protected abstract string DefinitionColumnName { get; }
        protected abstract string ParentIdColumnName { get; }
        protected abstract string TreeLevelColumnName { get; }
        protected abstract string StatusColumnName { get; }
        protected const string ErrorFieldNull = "The field '{0}' can not be null";

        private PropertyInfo CodeProperty { get { return typeof(T).GetProperty("Code"); } }
        private PropertyInfo DescriptionProperty { get { return typeof(T).GetProperty("Description"); } }
        private PropertyInfo DefinitionProperty { get { return typeof(T).GetProperty("Definition"); } }
        private PropertyInfo ParentIdProperty { get { return typeof(T).GetProperty("ParentId"); } }
        private PropertyInfo TreeLevelProperty { get { return typeof(T).GetProperty("TreeLevel"); } }
        private PropertyInfo StatusProperty { get { return typeof(T).GetProperty("Status"); } }

        protected List<Definition<T>> GetDefinitions()
        {
            return new List<Definition<T>>
            {
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = IdColumnName, CustomConversionMethod = ValidateId},
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = DescriptionColumnName, CustomConversionMethod = ValidateDescription},
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = DefinitionColumnName, CustomConversionMethod = ValidateDefinition},
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = ParentIdColumnName, CustomConversionMethod = ValidateParent},
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = TreeLevelColumnName, CustomConversionMethod = ValidateTreeLevel},
                new Definition<T> { ModelProperty = x => x.ConnectionString, ColumnName = StatusColumnName, CustomConversionMethod = ValidateStatus}
            };
        }

        private object ValidateDescription(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            return ValidateField(value, fields, out error, headers, DescriptionColumnName, typeof(string));
        }

        private object ValidateDefinition(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            return ValidateField(value, fields, out error, headers, DefinitionColumnName, typeof(string));
        }

        private object ValidateTreeLevel(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            return ValidateField(value, fields, out error, headers, TreeLevelColumnName, typeof(int));
        }

        private object ValidateStatus(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            return ValidateField(value, fields, out error, headers, StatusColumnName, typeof(string));
        }

        private static object ValidateField(string value, List<string> fields, out string error, List<string> headers, string columnName, Type type)
        {
            var field = fields[headers.IndexOf(Conversion.TransformColumnName(columnName))];

            if (string.IsNullOrWhiteSpace(field))
            {
                error = String.Format(ErrorFieldNull, columnName);
                return Conversion.Validation.Failed;
            }

            var valueConverted = new Definition<T>().ConvertType(value, type, null, out error);

            return valueConverted ?? Conversion.Validation.Failed;
        }

        private object ValidateId(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            //var domain = CacheFacade.Get(new Utils.GeneralAction().SelectAllActive<T>).FirstOrDefault(x => x.Code == value);

            //if (domain != null)
            //{
            //    if (!domain.Gocs.Any())
            //        model = domain;
            //    else
            //    {
            //        var description = fields[headers.IndexOf(Conversion.TransformColumnName("DESCRIPTION"))];
            //        var definition = fields[headers.IndexOf(Conversion.TransformColumnName("DEFINITION"))];
            //        var status = fields[headers.IndexOf(Conversion.TransformColumnName("STATUS"))];

            //        if (domain.Description == description && domain.Definition == definition
            //            && domain.Status == status)
            //        {
            //            model = domain;
            //        }
            //    }
            //}

            return value;
        }

        private object ValidateParent(ref T model, string value, List<string> fields, ref string error, List<string> headers = null)
        {
            var id = fields[headers.IndexOf(Conversion.TransformColumnName("FUNCTION_ID"))];

            //if (id == value)
            //    return Conversion.Validation.Validated;

            //var domain = CacheFacade.Get(new Function().SelectAllActive<Function>).FirstOrDefault(x => x.Code == value);

            //model.Parent = domain ?? new Function { Code = value };

            return Conversion.Validation.ManuallyValidated;
        }

        #endregion
    }
}
